﻿using System;

namespace HYGE.AsyncCommand
{
    /// <summary>
    /// CanExecuteのPush通知版AsyncActionCommand。
    /// </summary>
    public class ReactiveAsyncActionCommand : ReactiveAsyncCommandBase
    {
        #region Fields

        #region asyncCommand
        /// <summary>
        /// 処理を移譲するAsyncActionCommand。
        /// </summary>
        private AsyncActionCommand asyncCommand = null;
        #endregion

        #endregion

        #region Constructors

        #region Default
        /// <summary>
        /// デフォルトコンストラクタ。
        /// </summary>
        /// <param name="executeAsync"></param>
        /// <param name="onCompleted"></param>
        /// <param name="onError"></param>
        /// <param name="describeJob"></param>
        /// <param name="canExecuteSource"></param>
        /// <param name="initialCanExecute"></param>
        public ReactiveAsyncActionCommand(Action executeAsync, Action<int> onCompleted = null, Action<int, AggregateException> onError = null, Func<string> describeJob = null, IObservable<bool> canExecuteSource = null, bool initialCanExecute = false)
            : base(canExecuteSource, initialCanExecute)
        {
            //処理移譲AsyncCommand生成
            this.asyncCommand = new AsyncActionCommand(executeAsync, onCompleted, onError, describeJob);

            //イベントハンドラ登録
            this.asyncCommand.JobCreated += asyncCommand_JobCreated;
        }
        #endregion

        #endregion

        #region EventHandlers

        #region asyncCommand_JobCreated
        /// <summary>
        /// asyncCommandのJobCreatedイベントハンドラ。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void asyncCommand_JobCreated(object sender, JobCreatedEventArgs e)
        {
            this.OnJobCreated(e.CreatedJob);
        }
        #endregion

        #endregion

        #region OverrideMethods

        #region Execute
        /// <summary>
        /// Executeのオーバーライド。
        /// </summary>
        /// <param elementName="parameter"></param>
        protected override void Execute(object parameter)
        {
            this.asyncCommand.Execute();
        }
        #endregion

        #endregion

        #region PublicMethods

        #region Execute
        /// <summary>
        /// 公開用のExecute。Execute()にシグネチャ変更。
        /// </summary>
        public void Execute()
        {
            this.Execute(null);
        }
        #endregion

        #endregion
    }

    /// <summary>
    /// CanExecuteのPush通知版AsyncActionCommand{T}。
    /// </summary>
    public class ReactiveAsyncActionCommand<T> : ReactiveAsyncCommandBase
    {
        #region Fields

        #region asyncCommand
        /// <summary>
        /// 処理を移譲するAsyncActionCommand。
        /// </summary>
        private AsyncActionCommand<T> asyncCommand = null;
        #endregion

        #endregion

        #region Constructors

        #region Default
        public ReactiveAsyncActionCommand(Action<T> executeAsync, Action<int> onCompleted = null, Action<int, AggregateException> onError = null, Action<int> onCanceled = null, Func<T, string> describeJob = null, IObservable<bool> canExecuteSource = null, bool initialCanExecute = false)
            : base(canExecuteSource, initialCanExecute)
        {
            //処理移譲AsyncCommand生成
            this.asyncCommand = new AsyncActionCommand<T>(executeAsync, onCompleted, onError, onCanceled, describeJob);

            //イベントハンドラ登録
            this.asyncCommand.JobCreated += asyncCommand_JobCreated;
        }
        #endregion

        #endregion

        #region EventHandlers

        #region asyncCommand_JobCreated
        /// <summary>
        /// asyncCommandのJobCreatedイベントハンドラ。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void asyncCommand_JobCreated(object sender, JobCreatedEventArgs e)
        {
            this.OnJobCreated(e.CreatedJob);
        }
        #endregion

        #endregion

        #region OverrideMethods

        #region Execute
        /// <summary>
        /// Executeのオーバーライド。
        /// </summary>
        /// <param elementName="parameter"></param>
        protected override void Execute(object parameter)
        {
            this.asyncCommand.Execute(parameter == null ? default(T) : (T)parameter);
        }
        #endregion

        #endregion

        #region PublicMethods

        #region Execute
        /// <summary>
        /// 公開用のExecute。Execute(T)にシグネチャ変更。
        /// </summary>
        public void Execute(T parameter)
        {
            this.Execute((object)parameter);
        }
        #endregion

        #endregion
    }
}
